<?php

/**
 * Базовый класс для контроллеров админской части сайта.
 */
class Workset_Controller_Action_Admin extends Zend_Controller_Action {

    const NAVIGATION_CONFIG = 'admin';

    private static $_accessGroups = array();

    /**
     * Подключаемые файлы стилей
     */
    protected $_layoutCssLink = array();

    /**
     * Инлайновые вставки стилей
     */
    protected $_layoutCssStyle = array();

    /**
     * Инлайновые вставки скриптов
     */
    protected $_layoutScript = array();

    /**
     * Подключаемые файлы скриптов
     */
    protected $_layoutScriptFile = array();

    /**
     * Заголовок страницы
     */
    protected $_layoutPageTitle = '';

    /**
     * Навигация страницы
     */
    protected $_layoutNavigation = null;

    /**
     * Параметры действия
     */
    protected $_actionConfig = array();

    /**
     * Настройки локализации
     */
    protected $_actionLangConfig = array();

    /**
     * Подключать JQueryGrid
     */
    protected $_enableJQueryGrid = false;

    /**
     * Использование транслятора
     */
    protected $_translate = null;

	protected $_locale = null;

    protected $_navigationId = null;

	protected $_navigationInit = false;

	protected $_navigationActiveItem = null;

    protected $_navigationParams = array();

    /*
     * Пункты меню (Zend_Navigation)
     */
	protected $_navItems = array();

    static function addDefaultAccessGroup($group) {
        if (!in_array($group, self::$_accessGroups)) {
            self::$_accessGroups[] = $group;
        }
    }

    static function setDefaultAccessGroup($group) {
        self::$_accessGroups = (array)$group;
    }

    protected static function checkGroup($groups = null) {
        $user = Users_Model_User::getUser();
        if (!$user) {
            return false;
        }

        if (null === $groups) {
            $groups = self::$_accessGroups;
        }

        if (!$groups) {
            return true;
        }
        
        return $user->isAdmin() || $user->inGroup(self::$_accessGroups);
    }

    protected static function checkResource($resource, $privilege) {
        $user = Users_Model_User::getUser();
        if (!$user) {
            return false;
        }

        return $user->isAllowed($resource, $privilege);
    }

	protected function _getLayoutNavigation() {
		if (null === $this->_layoutNavigation) {

			$this->_layoutNavigation = new Zend_Navigation();

            $this->_initNavigationParams();

			$modules = Workset_Module::getRegisteredModules();

			foreach ($modules as $module) {

                $config = Workset_Module::getModuleOptions($module, 'navigation');
                
                if (null === $config) {
                    $config = self::NAVIGATION_CONFIG;
                }

                //добавляем навигацию контроллеров
                if (!is_array($config)) {
                    $config = $this->_helper->moduleConfig->getConfig("navigation/{$config}", null, $module);
                }

                $this->_layoutNavigation->addPages($config);
			}
		}

		return $this->_layoutNavigation;
	}

	protected function _addObjectToNavigation(Workset_Model_Object_Abstract $object, $pos = 'append') {
		$uri = $object->getUrl('navigation');
		$label = $object->getLabel('navigation');

		if ($uri && $label) {
			$spec = array(
				'label' => $label,
				'title' => $label,
				'uri' => $uri,
				'id' => 'navobj-'.$object->getId(),
				'ignore' => true,
				'active' => false
			);

			$this->_navItems[] = array(
				'spec' => $spec,
				'pos' => $pos
			);
		}
	}

	protected function _addNavItem($spec, $pos = 'append') {
		if (is_array($spec)) {
            $spec = array_merge(array(
                'ignore' => true,
                'active' => false,
                'id' => uniqid('navitem')
            ), $spec);

            if (!isset($spec['uri'])) {
                if (!isset($spec['action'])) {
                    $spec['action'] = $this->_request->getActionName();
                }

                if (!isset($spec['controller'])) {
                    $spec['controller'] = $this->_request->getControllerName();
                }

                if (!isset($spec['module'])) {
                    $spec['module'] = $this->_request->getModuleName();
                }
            }

			$this->_navItems[] = array(
				'spec' => $spec,
				'pos' => $pos
			);
		} elseif ($spec instanceof Workset_Model_Object_Abstract) {
			$this->_addObjectToNavigation($spec, $pos);
		}
	}

    protected function _initNavigationParams() {
		if (Zend_Registry::isRegistered('navigationParams')) {
			$this->_navigationParams = array_merge($this->_navigationParams, (array)Zend_Registry::get('navigationParams'));
		}

        if (!isset($this->_navigationParams['module'])) {
            $this->_navigationParams['module'] = $this->_request->getModuleName();
        }

        if (!isset($this->_navigationParams['controller'])) {
            $this->_navigationParams['controller'] = $this->_request->getControllerName();
        }

        if (!isset($this->_navigationParams['action'])) {
            $this->_navigationParams['action'] = $this->_request->getActionName();
        }
    }

    protected function _checkNavigationAccess(Zend_Navigation_Container $nav) {
        while ($nav->valid()) {

            $item = $nav->current();

            $nav->next();

            if ($item->resource) {
                $allowed = Users_Model_User::getUser()->isAllowed($item->resource, $item->privilege);
            } else {
                $allowed = true;
            }

            if (!$allowed) {
                $item->getParent()->removePage($item);

            } elseif ($item->hasChildren()) {
                $this->_checkNavigationAccess($item->getChildren());

            }
        }
    }

	protected function _initNavigation() {
		if (false != $this->_navigationInit) {
			return;
		}

		$nav = $this->_getLayoutNavigation();

        //проверка прав доступа к пунктам меню
        $this->_checkNavigationAccess($nav);

        //ищем главный пункт текущего модуля
        $rootItem = null;
        $checkItems = $nav->findAllBy('module', $this->_navigationParams['module']);
        if ($checkItems) {
            if (count($checkItems) == 1) {
                $rootItem = current($checkItems);
            } else {
                foreach ($checkItems as $item) {
                    if ($item->controller == $this->_navigationParams['controller']) {
                        $rootItem = $item;
                        break;
                    }
                }
            }
        }

		if (!$rootItem) {
			return;
		}

		$activeItem = $rootItem->findOneBy('active', true);

		if (!$activeItem) {
			//ищем активный пункт в цепочке
			if (!empty($this->_actionConfig['parent_action'])) {

                if (!isset($this->_actionConfig['parent_navigation_item']) || false != $this->_actionConfig['parent_navigation_item']) {
                    $items = $rootItem->findAllBy('controller', $this->_navigationParams['controller']);
                    foreach ($items as $item) {
                        if ($item->getAction() == $this->_actionConfig['parent_action']) {
                            $activeItem = $item;
                            $activeItem->setActive(true);
                        }
                    }
                }

			}

			if (!$activeItem) {
				$activeItem = $rootItem;
				$activeItem->setActive(true);
			}
		}

		if ($this->_navItems) {
			$this->_navActiveItem = $item = null;

            try {

                for ($i = 0, $cnt = count($this->_navItems); $i < $cnt; $i++) {
                    $options = $this->_navItems[$i];
                    $pos = $options['pos'];

                    if (null === $item) {
                        //@todo today impl. 'append' type only
                        if ($pos == 'append') {
                            $item = $activeItem;
                            $item->setActive(false);
                        }
                    }

                    $item->addPage($options['spec']);
                    $item = $item->findOneBy('id', $options['spec']['id']);
                }

                $activeItem = $item;
                $activeItem->setActive(true);

            } catch (Zend_Exception $e) {
                $this->_response->setException($e);
                return;
            }
		}

		if ($activeItem) {
			$this->_navigationInit = true;
			$this->_navigationActiveItem = $activeItem;
		}

		//dump($rootItem->toArray()); exit;
		return $activeItem;
	}

	protected function _initActionConfig() {
		//настройки модуля
        $this->_actionConfig = $this->_helper->moduleConfig->getConfig($this->_request->getModuleName('module'));

        //настройки контроллера
        if (!empty($this->_actionConfig['load_controller_config'])) {
            $this->_actionConfig = array_merge(

                $this->_actionConfig,

                $this->_helper->moduleConfig->getConfig(implode(DIRECTORY_SEPARATOR, array(
                    'controllers', $this->_request->getControllerName('controller')
                )), null, null, $this->_actionConfig)

            );
        }

        //настройки действия
        if (!empty($this->_actionConfig['load_action_config'])) {
            $this->_actionConfig = array_merge(

                $this->_actionConfig,

                $this->_helper->moduleConfig->getConfig(implode(DIRECTORY_SEPARATOR, array(
                    'controllers', $this->_request->getControllerName('controller'), $this->_request->getActionName('action')
                )), null, null, $this->_actionConfig)

            );

            $configs = array();

			//настройки из "родительского" действия
            if (!empty($this->_actionConfig['parent_action'])) {
                $configs[] = $this->_actionConfig['parent_action'];
            }

			//настройки из других действий
            if (!empty($this->_actionConfig['load_config'])) {
                $configs = array_merge((array)$this->_actionConfig['load_config'], $configs);
            }

            foreach ($configs as $config) {
                $config = $this->_helper->moduleConfig->getConfig(implode(DIRECTORY_SEPARATOR, array(
                    'controllers', $this->_getParam('controller'), $config
                )), null, null, $this->_actionConfig);

                //$this->_actionConfig = array_merge($this->_actionConfig, $config) ;
                $this->_actionConfig += $config ;
            }
        }
	}

	protected function _checkAccess() {

		$checked = false;

		if (!Workset_Module::hasModule('users')) {
			return $checked;
		}

		if (!empty($this->_actionConfig['access_checked'])) {

			$checked = true;

		} elseif (!empty($this->_actionConfig['access_resource'])) {

			$resource = $this->_actionConfig['access_resource'];

            if (!empty($this->_actionConfig['access_privilege'])) {
                $privilege = $this->_actionConfig['access_privilege'];
            } else {
                $privilege = $this->_request->getActionName();
            }

			$checked = self::checkResource($resource, $privilege);

        } elseif (!empty($this->_actionConfig['access_by_default'])) {

			$checked = true;
			
        } else {
			$checked = Users_Model_User::getUser()->isAdmin();
		}

		return $checked;
	}

    function preDispatch() {

        //инициализация конфига котроллера
        $this->_initActionConfig();

        $this->_setParam('redirects', array(
            401 => array(
                'module' => 'users',
                'controller' => 'admin',
                'action' => 'login',
            ),
            403 => array(
                'module' => 'users',
                'controller' => 'admin',
                'action' => 'login',
            ),
        ));

        $this->_setParam('json_message', true);

        //Для указания настроек текущего action из другого action
        if (Zend_Registry::isRegistered('actionConfig')) {
            $overwrite = Zend_Registry::get('actionConfig');
            if (is_array($overwrite)) {
                $this->_actionConfig = array_merge($this->_actionConfig, $overwrite);
            }
        }

		//проверка прав доступа
		if (!$this->_checkAccess()) {
			if (Workset_Auth::getInstance()->hasIdentity()) {
				throw new Zend_Exception('Access denied', 403);
			}
			else {
				$this->_redirect(
					$this->_helper->url('login', 'admin', 'users', array(
						'backurl' => $this->_request->getRequestUri()
					))
				);
			}
		}

		//перевод действия
		$this->_actionLangConfig = $this->_helper->moduleConfig->getConfig(implode(DIRECTORY_SEPARATOR, array(
            'lang', $this->_locale, 'controllers',
            $this->_request->getControllerName('controller'),
            $this->_request->getActionName('action')
        )));

        //настраиваем транслятор
        if (!empty($this->_actionConfig['action_translate']) && Zend_Registry::isRegistered('Zend_Translate')) {
           $this->_translate = Zend_Registry::get('Zend_Translate');
           $this->_translate->addTranslation(array('content' => $this->_actionLangConfig));
        }

    }

    /**
     * Настройки layout.
     *
     * @return void
     */
    function postDispatch() {
 
		//если не нужно ничего обрабатывать
        $handlePostDispatch = $this->_getParam('handlePostDispatch');
        if ($handlePostDispatch === false) {
            return;
        }

		$this->_setParam('handlePostDispatch', false);

        $layout = Zend_Layout::getMvcInstance();

		//если layout не подключен, ничего делать не нужно
        if (null === $layout) {
            return;
        }

        //замена стандартного layout на layout админки модуля.
        if (isset($this->_actionConfig['layout_script'])) {
            if (!$this->_response->isException()) {
                $layout->setLayout($this->_actionConfig['layout_script']);
            } else {
                //показ ошибок в текущем layout
                $this->_setParam('error_resp_segment', 'exception');
                $this->_setParam('error_layout_script', $this->_actionConfig['layout_script']);
            }
        }

		//jquery UI
        $jq = $this->view->JQuery()->enable()->uiEnable();

        //стили главного меню
		$jq->addJavascriptFile('/js/menu.js');
		$jq->addJavascriptFile('/js/utilites.js');
		$jq->addStylesheet('/css/apycom.menu/menu.css');

        // Отображение таблиц с данными.
        if ($this->_enableJQueryGrid) {
			$jq->addStylesheet('/css/jqgrid/ui.jqgrid.css');
			$jq->addStylesheet('/css/jqgrid/ui.multiselect.css');

			$jq->addJavascriptFile('/js/jqgrid/ui.multiselect.js');
			$jq->addJavascriptFile('/js/jqgrid/i18n/grid.locale-ru.js');
			$jq->addJavascriptFile('/js/jqgrid/jquery.jqGrid.js');
            $this->_layoutScriptFile[] = '/js/jquery.form.js';
        }

		//дополнительные стили интерфейса
		$jq->addStylesheet('/css/admin/style.css');

        //пункт меню текущего действия
		$this->_initNavigation();

        //заголовок страницы
        if (!$this->_layoutPageTitle) {
            if ($this->_navigationActiveItem) {
                $this->_layoutPageTitle = $this->_navigationActiveItem->title;
            } else {
                $this->_layoutPageTitle = '&nbsp;';
            }
        }

        //рендеринг меню модуля.
		$layout->menu = $this->view->navigation($this->_layoutNavigation)
                                   ->setTranslator($this->_translate)
                                   ->menu()
                                   ->setPartial($this->_actionConfig['menu_script']);

        //рендеринг цепочки навигации
        $layout->breadcrumbs = $this->view->navigation($this->_layoutNavigation)->breadcrumbs();

		if (!empty($this->_actionLangConfig['title'])) {
			//if (empty($this->_layoutPageTitle)) {
				$this->_layoutPageTitle =  $this->_actionLangConfig['title'];
			//} 
		}

        //рендеринг других placeholders (доп. стили, скрипты, ...)
        $this->_helper->actionLayout(array(
            'cssLink' => $this->_layoutCssLink,
            'cssStyle' => $this->_layoutCssStyle,
            'script' => $this->_layoutScript,
            'scriptFile' => $this->_layoutScriptFile,
            'pageTitle' => $this->_layoutPageTitle
        ));

        $this->_clearConfig();

    }

	/**
	 * (non-PHPdoc)
	 * @see library/Zend/Controller/Zend_Controller_Action#init()
	 */
    function init() {
		$this->_locale = Zend_Locale::findLocale(null);
    }

    function getActionConfig() {
        return $this->_actionConfig;
    }

    function getActionLangConfig() {
        return $this->_actionLangConfig;
    }

    protected function _clearConfig() {
        $this->_actionConfig = array();
        $this->_actionLangConfig = array();
        $this->_enableJQueryGrid = false;
        $this->_translate = null;
        $this->_layoutCssLink = array();
        $this->_layoutCssStyle = array();
        $this->_layoutScript = array();
        $this->_layoutScriptFile = array();
        $this->_layoutNavigation = null;
        $this->_layoutPageTitle = '';
    }
}
?>